package com.shrct.businessprocess.purchase.impl;

import com.shrct.businessprocess.budget.RCBudget;
import com.shrct.businessprocess.budget.RCCostBreakDown;
import com.shrct.businessprocess.diagnose.IDiagnoseAcceptor;
import com.shrct.businessprocess.money.Moneys;
import com.shrct.businessprocess.project.RCExchangeRate;
import com.shrct.businessprocess.project.RCProject;
import com.shrct.businessprocess.project.RCProjectMoney;
import com.shrct.businessprocess.project.RCProjectStat;
import com.shrct.businessprocess.purchase.RCBasePurchasePayRequest;
import com.shrct.businessprocess.purchase.RCHasPurchaseBudget;
import com.shrct.businessprocess.purchase.RCPurchaseOrderInvoice;
import com.shrct.businessprocess.purchase.RCServiceProductPurchaseRequest;
import com.shrct.businessprocess.purchase.RCServicePurchaseOrder;
import com.shrct.businessprocess.purchase.RCServicePurchaseOrderAccept;
import com.shrct.businessprocess.purchase.RCServicePurchaseOrderStatus;
import com.shrct.businessprocess.purchase.impl.RCBasePurchaseOrderImpl;
import com.shrct.businessprocess.purchase.impl.RCServiceProductPurchaseRequestImpl;
import com.shrct.businessprocess.purchase.impl.RCServicePurchaseOrderAcceptImpl;
import com.shrct.businessprocess.purchase.proxy.RCServicePurchaseOrderProxy;
import edu.fudan.langlab.domain.statemachine.ModelObjectLogService;
import edu.fudan.mylang.pf.IObjectFactory;
import edu.fudan.mylang.utils.DateUtil;
import java.util.Collection;
import java.util.Date;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;

@Entity
@DiscriminatorValue("RCSERVICEPURCHASEORDER_TYPE")
public class RCServicePurchaseOrderImpl extends RCBasePurchaseOrderImpl implements RCServicePurchaseOrder {
  public RCServicePurchaseOrderImpl() {
    super();
  }
  
  public RCServicePurchaseOrderImpl(final RCServiceProductPurchaseRequest purchaseRequest) {
    super();
    this.purchaseRequest = purchaseRequest;
  }
  
  private RCServicePurchaseOrderStatus Status;
  
  public RCServicePurchaseOrderStatus getStatus() {
    return this.Status;
  }
  
  private ModelObjectLogService getModelObjectLogService() {
    return getBeanFactory().getBean(ModelObjectLogService.class);
  }
  
  private void _start() {
    
    Status=RCServicePurchaseOrderStatus.craeted;
  }
  
  public void start() {
    if(Status==null){
    	_start();
    	getModelObjectLogService().createLog(this,"Status","Start");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).fireStarted(this);					
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("allready started");
    }
  }
  
  private void _startAudit() {
    
    Status=RCServicePurchaseOrderStatus.auditing;
  }
  
  public void startAudit() {
    if(Status==RCServicePurchaseOrderStatus.craeted){
    	_startAudit();
    	getModelObjectLogService().createLog(this,"Status","startAudit");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).fireStartAudit(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _auditPassed() {
    
    this.setIsInitialized(Boolean.valueOf(true));
    Date _day = DateUtil.today();
    this.setInitializeDate(_day);
    Status=RCServicePurchaseOrderStatus.executing;
  }
  
  public void auditPassed() {
    if(Status==RCServicePurchaseOrderStatus.auditing){
    	_auditPassed();
    	getModelObjectLogService().createLog(this,"Status","auditPassed");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).fireAuditPassed(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _auditCanceled() {
    
    Status=RCServicePurchaseOrderStatus.canceled;
  }
  
  public void auditCanceled() {
    if(Status==RCServicePurchaseOrderStatus.auditing){
    	_auditCanceled();
    	getModelObjectLogService().createLog(this,"Status","auditCanceled");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).fireAuditCanceled(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _invoiceRegister() {
    
    Status=RCServicePurchaseOrderStatus.executing;
  }
  
  public void invoiceRegister() {
    if(Status==RCServicePurchaseOrderStatus.executing){
    	_invoiceRegister();
    	getModelObjectLogService().createLog(this,"Status","invoiceRegister");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).fireInvoiceRegister(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _payRequest() {
    
    Status=RCServicePurchaseOrderStatus.executing;
  }
  
  public void payRequest() {
    if(Status==RCServicePurchaseOrderStatus.executing){
    	_payRequest();
    	getModelObjectLogService().createLog(this,"Status","payRequest");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).firePayRequest(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _close() {
    
    RCHasPurchaseBudget _budget = this.purchaseRequest.getBudget();
    RCCostBreakDown _cbd = _budget.getCbd();
    RCProject _project = _cbd.getProject();
    RCProjectStat _stat = _project.getStat();
    _stat.updateInfo();
    this.setIsClosed(Boolean.valueOf(true));
    Status=RCServicePurchaseOrderStatus.closed;
  }
  
  public void close() {
    if(Status==RCServicePurchaseOrderStatus.executing){
    	_close();
    	getModelObjectLogService().createLog(this,"Status","close");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).fireClose(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _postCancel() {
    
    boolean _or = false;
    boolean _or_1 = false;
    int _size = this.acceptItems.size();
    boolean _notEquals = (_size != 0);
    if (_notEquals) {
      _or_1 = true;
    } else {
      Collection<RCBasePurchasePayRequest> _payRequests = this.getPayRequests();
      int _size_1 = _payRequests.size();
      boolean _notEquals_1 = (_size_1 != 0);
      _or_1 = (_notEquals || _notEquals_1);
    }
    if (_or_1) {
      _or = true;
    } else {
      Collection<RCPurchaseOrderInvoice> _invoices = this.getInvoices();
      int _size_2 = _invoices.size();
      boolean _notEquals_2 = (_size_2 != 0);
      _or = (_or_1 || _notEquals_2);
    }
    if (_or) {
      RuntimeException _runtimeException = new RuntimeException("Invalid state");
      throw _runtimeException;
    }
    this.setIsInitialized(Boolean.valueOf(false));
    this.setInitializeDate(null);
    Status=RCServicePurchaseOrderStatus.canceled;
  }
  
  public void postCancel() {
    if(Status==RCServicePurchaseOrderStatus.executing){
    	_postCancel();
    	getModelObjectLogService().createLog(this,"Status","postCancel");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).firePostCancel(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _cancelClose() {
    
    this.setIsClosed(Boolean.valueOf(false));
    RCHasPurchaseBudget _budget = this.purchaseRequest.getBudget();
    RCCostBreakDown _cbd = _budget.getCbd();
    RCProject _project = _cbd.getProject();
    RCProjectStat _stat = _project.getStat();
    _stat.updateInfo();
    Status=RCServicePurchaseOrderStatus.executing;
  }
  
  public void cancelClose() {
    if(Status==RCServicePurchaseOrderStatus.closed){
    	_cancelClose();
    	getModelObjectLogService().createLog(this,"Status","cancelClose");
    	getBeanFactory().getBean(com.shrct.businessprocess.purchase.events.RCServicePurchaseOrderEventsManager.class).fireCancelClose(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  public Boolean isCraeted() {
    return com.shrct.businessprocess.purchase.RCServicePurchaseOrderStatus.craeted==Status;
  }
  
  public Boolean isAuditing() {
    return com.shrct.businessprocess.purchase.RCServicePurchaseOrderStatus.auditing==Status;
  }
  
  public Boolean isExecuting() {
    return com.shrct.businessprocess.purchase.RCServicePurchaseOrderStatus.executing==Status;
  }
  
  public Boolean isClosed() {
    return com.shrct.businessprocess.purchase.RCServicePurchaseOrderStatus.closed==Status;
  }
  
  public Boolean isCanceled() {
    return com.shrct.businessprocess.purchase.RCServicePurchaseOrderStatus.canceled==Status;
  }
  
  @JoinColumn(name = "purchaseRequest_id")
  @ManyToOne(targetEntity = RCServiceProductPurchaseRequestImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCServiceProductPurchaseRequest purchaseRequest;
  
  public RCServiceProductPurchaseRequest getPurchaseRequest() {
    return this.purchaseRequest;
  }
  
  public RCServicePurchaseOrder setPurchaseRequest(final RCServiceProductPurchaseRequest purchaseRequest) {
    this.purchaseRequest = purchaseRequest;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "amount", column = @Column(name = "amount_amount") ), @AttributeOverride(name = "workaround", column = @Column(name = "amount_workaround") ) } )
  @AssociationOverrides(value = @AssociationOverride(name = "exchange", joinColumns = @JoinColumn(name = "amount_exchange") ) )
  private RCProjectMoney amount = com.shrct.businessprocess.project.RCProjectMoney.create();
  
  public RCProjectMoney getAmount() {
    return this.amount;
  }
  
  public RCServicePurchaseOrder setAmount(final RCProjectMoney amount) {
    this.amount = amount;
    return this;			
    
  }
  
  private String comment;
  
  public String getComment() {
    return this.comment;
  }
  
  public RCServicePurchaseOrder setComment(final String comment) {
    this.comment = comment;
    return this;			
    
  }
  
  @OneToMany(targetEntity = RCServicePurchaseOrderAcceptImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "purchaseOrder")
  private Collection<RCServicePurchaseOrderAccept> acceptItems = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCServicePurchaseOrderAccept>();;
  
  public Collection<RCServicePurchaseOrderAccept> getAcceptItems() {
    return this.acceptItems;
  }
  
  public RCServicePurchaseOrderAccept createAndAddtoAcceptItems() {
    getAcceptItems().size();
    com.shrct.businessprocess.purchase.RCServicePurchaseOrderAccept rCServicePurchaseOrderAccept = new com.shrct.businessprocess.purchase.impl.RCServicePurchaseOrderAcceptImpl(this);
    getObjectFactory().create(rCServicePurchaseOrderAccept);
    getAcceptItems().add(rCServicePurchaseOrderAccept);
    return rCServicePurchaseOrderAccept;
    
  }
  
  public RCServicePurchaseOrderAccept createAndAddtoAcceptItems(final Procedure1<RCServicePurchaseOrderAccept> updater) {
    getAcceptItems().size();
    com.shrct.businessprocess.purchase.RCServicePurchaseOrderAccept rCServicePurchaseOrderAccept = new com.shrct.businessprocess.purchase.impl.RCServicePurchaseOrderAcceptImpl(this);
    getObjectFactory().create(rCServicePurchaseOrderAccept);
    getAcceptItems().add(rCServicePurchaseOrderAccept);
    return rCServicePurchaseOrderAccept;
    
  }
  
  public RCServicePurchaseOrder removeAllAcceptItems() {
    for(RCServicePurchaseOrderAccept obj : this.acceptItems){
    	getObjectFactory().delete(obj);
    }
    this.acceptItems.clear();
    return this;	
    
  }
  
  public RCServicePurchaseOrder removeFromAcceptItems(final RCServicePurchaseOrderAccept rCServicePurchaseOrderAccept) {
    this.acceptItems.remove(rCServicePurchaseOrderAccept);
    getObjectFactory().delete(rCServicePurchaseOrderAccept);
    return this;
    
  }
  
  public RCBudget getBudget() {
    RCHasPurchaseBudget _budget = this.purchaseRequest.getBudget();
    return _budget;
  }
  
  public void diagnose(final IDiagnoseAcceptor acceptor) {
  }
  
  /**
   * 订单总金额
   */
  public RCProjectMoney getTotalCost() {
    return this.amount;
  }
  
  public RCServicePurchaseOrderAccept createAccept(final Procedure1<? super RCServicePurchaseOrderAccept> preInit) {
    RCServicePurchaseOrderAccept _createAndAddtoAcceptItems = this.createAndAddtoAcceptItems();
    final Procedure1<RCServicePurchaseOrderAccept> _function = new Procedure1<RCServicePurchaseOrderAccept>() {
        public void apply(final RCServicePurchaseOrderAccept it) {
          preInit.apply(it);
        }
      };
    RCServicePurchaseOrderAccept _doubleArrow = ObjectExtensions.<RCServicePurchaseOrderAccept>operator_doubleArrow(_createAndAddtoAcceptItems, _function);
    return _doubleArrow;
  }
  
  public RCProjectMoney getTotalAcceptItemsAmount() {
    final Function1<RCServicePurchaseOrderAccept,RCProjectMoney> _function = new Function1<RCServicePurchaseOrderAccept,RCProjectMoney>() {
        public RCProjectMoney apply(final RCServicePurchaseOrderAccept it) {
          RCProjectMoney _totalAmount = it.getTotalAmount();
          return _totalAmount;
        }
      };
    Iterable<RCProjectMoney> _map = IterableExtensions.<RCServicePurchaseOrderAccept, RCProjectMoney>map(this.acceptItems, _function);
    RCExchangeRate _defaultExchangeRate = this.getDefaultExchangeRate();
    RCProjectMoney _sum = Moneys.sum(_map, _defaultExchangeRate);
    return _sum;
  }
  
  public static RCServicePurchaseOrder create(final RCServiceProductPurchaseRequest purchaseRequest, final IObjectFactory objectFactory) {
    com.shrct.businessprocess.purchase.RCServicePurchaseOrder rCServicePurchaseOrder = new com.shrct.businessprocess.purchase.impl.RCServicePurchaseOrderImpl(
    	purchaseRequest
    );
    objectFactory.create(rCServicePurchaseOrder);
    return rCServicePurchaseOrder;			
    
  }
  
  public static RCServicePurchaseOrder createRCServicePurchaseOrderImpl(final RCServiceProductPurchaseRequest purchaseRequest, final IObjectFactory objectFactory, final Procedure1<RCServicePurchaseOrder> init) {
    com.shrct.businessprocess.purchase.RCServicePurchaseOrder rCServicePurchaseOrder = new com.shrct.businessprocess.purchase.impl.RCServicePurchaseOrderImpl(
    	purchaseRequest
    );
    objectFactory.create(rCServicePurchaseOrder);
    init.apply(rCServicePurchaseOrder);
    
    return rCServicePurchaseOrder;			
    
  }
  
  public RCServicePurchaseOrderProxy toProxy() {
    com.shrct.businessprocess.purchase.proxy.RCServicePurchaseOrderProxy proxy = new com.shrct.businessprocess.purchase.proxy.RCServicePurchaseOrderProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    proxy.setStatus(this.getStatus().name());
    return proxy;
    
  }
}
